package cn.bytets.rpc.api.message;

import cn.bytets.rpc.api.invoke.Invocation;

import java.util.concurrent.CompletableFuture;

/**
 *此类表示未完成的 RPC 调用，它将保存此调用的一些上下文信息，例如 RpcContext 和 Invocation，
 *以便在调用完成并返回结果时，它可以保证所有正在恢复的上下文与调用之前进行调用时相同。
 *
 *
 */
public class AsyncRpcResult extends AbstractResult{

    private Invocation invocation;

    public AsyncRpcResult(){

    }
    public AsyncRpcResult(Invocation invocation){
        this.invocation = invocation;
    }

    @Override
    public Object getValue() {
        return getAppResponse().getValue();
    }

    @Override
    public void setValue(Object value) {
        try{
            if (this.isDone()){
                this.get().setValue(value);
            } else {
                this.complete(new AppResponse(value));
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public Throwable getException() {
        return getAppResponse().getException();
    }

    @Override
    public void setException(Throwable exception) {
        try {
            if (this.isDone()){
                this.get().setException(exception);
            } else {
                this.complete(new AppResponse(exception));
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public boolean hasException() {
        return getAppResponse().hasException();
    }

    @Override
    public Object recreate() throws Throwable {
//        RpcInvocation rpcInvocation = (RpcInvocation) invocation;
//        FutureAdapter future = new FutureAdapter(this);
//        RpcContext.getContext().setFuture(future);
//        if (InvokeMode.FUTURE == rpcInvocation.getInvokeMode()) {
//            return future;
//        }
        return getAppResponse().recreate();
    }
    public Result getAppResponse() {
        try {
            if (this.isDone()) {
                return this.get();
            }
        } catch (Exception e) {
            // This should never happen;
            //logger.error("Got exception when trying to fetch the underlying result from AsyncRpcResult.", e);
            e.printStackTrace();
        }
        return new AppResponse();
    }

    public void subscribeTo(CompletableFuture<?> future) {
        future.whenComplete((obj, t) -> {
            if (t != null) {
                this.completeExceptionally(t);
            } else {
                this.complete((Result) obj);
            }
        }).exceptionally(ex->{
            System.out.println("Oops! We have an exception - " + ex.getMessage());
            this.completeExceptionally(ex);
            return null;
        });
    }
}
